#include "ObstacleManager.h"

// Initialize the instance to null
ObstacleManager* ObstacleManager::m_ObstacleInstance = 0;

ObstacleManager::ObstacleManager(void)
{
	sTeslaIndex = 0;
	sAcidIndex = 0;
	sPistonIndex = 0;
	sFirewallIndex = 0;
	lStartTime = 0;
}

ObstacleManager::~ObstacleManager(void)
{
}

// Singleton functions
ObstacleManager* ObstacleManager::GetInstance(void)
{
	// Create the instance if it doesn't exist
	if(!m_ObstacleInstance)
		m_ObstacleInstance = new ObstacleManager;

	// Return the singleton
	return m_ObstacleInstance;
}

void ObstacleManager::DeleteInstance(void)
{
	ObstacleManager::DestroyAllObstacles();
	// If instance exist, delete it!
	if(m_ObstacleInstance)
	{
		delete m_ObstacleInstance;
		m_ObstacleInstance = NULL;
	}
}

// Initializing the manager
void ObstacleManager::InitObstacleManager(IDirect3DDevice9* m_pD3DDevice)
{
	m_Device = m_pD3DDevice;

	modelMan = ModelManager::GetInstance();
}

// Return index values
short ObstacleManager::ReturnTeslaIndex(void)
{
	return sTeslaIndex;
}

short ObstacleManager::ReturnAcidIndex(void)
{
	return sAcidIndex;
}

short ObstacleManager::ReturnPistonIndex(void)
{
	return sPistonIndex;
}

short ObstacleManager::ReturnFirewallIndex(void)
{
	return sFirewallIndex;
}
// Load models
short ObstacleManager::CreateTeslaCoil(D3DXVECTOR3 vecPos)
{
	s_TeslaCoil* currentObstacle = new s_TeslaCoil;

	// Start .x loading
	LPD3DXBUFFER p_D3DXMtrlBuffer;
	currentObstacle->m_dwNumMaterials = 0;

	// Load .x file
	D3DXLoadMeshFromX( "Models\\Tesla.X", D3DXMESH_SYSTEMMEM,
		m_Device, NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials),
		&(currentObstacle->m_pMesh));

	D3DXMATERIAL* d3dxMaterials =
		(D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	// Create an array based on the amount of materials we have
	currentObstacle->m_pMaterials = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials];
	currentObstacle->m_pMeshTextures = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials];

	// Load each material
	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials; i++)
	{
		currentObstacle->m_pMaterials[i] = d3dxMaterials[i].MatD3D;

		currentObstacle->m_pMaterials[i].Ambient = currentObstacle->m_pMaterials[i].Diffuse;

		currentObstacle->m_pMeshTextures[i] = NULL;
		if( d3dxMaterials[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile( m_Device,
			d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures[i]));
		}
	}

	// Create Electrified Grahpic
	currentObstacle->m_dwNumMaterials2 = 0;
	D3DXLoadMeshFromX( "Models\\Elec.X", D3DXMESH_SYSTEMMEM, m_Device,
		NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials2),
		&(currentObstacle->m_pMesh2));

	D3DXMATERIAL* d3dxMaterials2 = (D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	currentObstacle->m_pMaterials2 = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials2];
	currentObstacle->m_pMeshTextures2 = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials2];

	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials2; i++)
	{
		currentObstacle->m_pMaterials2[i] = d3dxMaterials2[i].MatD3D;
		currentObstacle->m_pMaterials2[i].Ambient = currentObstacle->m_pMaterials2[i].Diffuse;
		currentObstacle->m_pMeshTextures2[i] = NULL;
		if( d3dxMaterials2[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile(m_Device, d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures2[i]));
		}
	}
	// End .x loading

	// Set the pos & scale for the model
	currentObstacle->vecScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
	currentObstacle->vecScale2 = D3DXVECTOR3(0.9f, 0.9f, 0.9f);
	currentObstacle->vecPos = vecPos;
	currentObstacle->vecPos2 = vecPos;
	currentObstacle->bCharged = false;
//	currentObstacle->sTimeCount = 0;
	
	D3DXCreateBox(m_Device, 3.4f, 2.0f, 3.4f, &m_pExtendedCollisionMesh, NULL);

	HRESULT hr = 0;
	BYTE* pVertices = 0;
	if( SUCCEEDED(m_pExtendedCollisionMesh->LockVertexBuffer(0, (void**)&pVertices)))
	{
		// Locking the vertex buffer so we can compute the bounds
		hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, m_pExtendedCollisionMesh->GetNumVertices(),
			D3DXGetFVFVertexSize(m_pExtendedCollisionMesh->GetFVF()), &currentObstacle->vecBBMin, 
			&currentObstacle->vecBBMax);

		// Unlock the vertex buffer
		m_pExtendedCollisionMesh->UnlockVertexBuffer();
		// with the min and max vectors we can get the 8 corners for the bounding box
		currentObstacle->vecModelBounds[0] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[1] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[2] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[3] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[4] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[5] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[6] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[7] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
	}

	// Get attributes to draw bounding box
	float width, height, depth;
	width = currentObstacle->vecBBMax.x - currentObstacle->vecBBMin.x;
	height = currentObstacle->vecBBMax.y - currentObstacle->vecBBMin.y;
	depth = currentObstacle->vecBBMax.z - currentObstacle->vecBBMin.z;

	// Make a mesh
	D3DXCreateBox(m_Device, width, height, depth, &m_pBBTeslaMesh, NULL);
	// Insert the current structure into the vector
	teslaList.push_back(currentObstacle);

	return sTeslaIndex++;
}

short ObstacleManager::CreateAcidPit(D3DXVECTOR3 vecPos)
{
	s_AcidPit* currentObstacle = new s_AcidPit;

	// Start .x loading
	LPD3DXBUFFER p_D3DXMtrlBuffer;
	currentObstacle->m_dwNumMaterials = 0;

	// Load .x file
	D3DXLoadMeshFromX( "Models\\Acid.X", D3DXMESH_SYSTEMMEM,
		m_Device, NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials),
		&(currentObstacle->m_pMesh));

	D3DXMATERIAL* d3dxMaterials =
		(D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	// Create an array based on the amount of materials we have
	currentObstacle->m_pMaterials = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials];
	currentObstacle->m_pMeshTextures = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials];

	// Load each material
	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials; i++)
	{
		currentObstacle->m_pMaterials[i] = d3dxMaterials[i].MatD3D;

		currentObstacle->m_pMaterials[i].Ambient = currentObstacle->m_pMaterials[i].Diffuse;

		currentObstacle->m_pMeshTextures[i] = NULL;
		if( d3dxMaterials[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile( m_Device,
			d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures[i]));
		}
	}
	// acid spray code, current form is a place holder for an actual particle system
	currentObstacle->m_dwNumMaterials2 = 0;
	D3DXLoadMeshFromX( "Models\\Bubbles.X", D3DXMESH_SYSTEMMEM, m_Device,
		NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials2),
		&(currentObstacle->m_pMesh2));

	D3DXMATERIAL* d3dxMaterials2 = (D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	currentObstacle->m_pMaterials2 = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials2];
	currentObstacle->m_pMeshTextures2 = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials2];

	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials2; i++)
	{
		currentObstacle->m_pMaterials2[i] = d3dxMaterials2[i].MatD3D;
		currentObstacle->m_pMaterials2[i].Ambient = currentObstacle->m_pMaterials2[i].Diffuse;
		currentObstacle->m_pMeshTextures2[i] = NULL;
		if( d3dxMaterials2[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile(m_Device, d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures2[i]));
		}
	}
	// End .x loading

	// Set the pos & scale for the model
	currentObstacle->vecScale = D3DXVECTOR3(0.4f, 0.4f, 0.4f);
	currentObstacle->vecScale2 = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
	currentObstacle->vecPos = vecPos;
	currentObstacle->vecPos2 = vecPos;
	currentObstacle->vecRot = D3DXVECTOR3(-1.570f, 0.0f, 0.0f);
	currentObstacle->bAcidSpray = true;

	D3DXCreateBox(m_Device, 8.0f, 10.0f, 16.0f, &m_pExtendedCollisionMesh, NULL);

	HRESULT hr = 0;
	BYTE* pVertices = 0;
	if( SUCCEEDED(m_pExtendedCollisionMesh->LockVertexBuffer(0, (void**)&pVertices)))
	{
		// Locking the vertex buffer so we can compute the bounds
		hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, m_pExtendedCollisionMesh->GetNumVertices(),
			D3DXGetFVFVertexSize(m_pExtendedCollisionMesh->GetFVF()), &currentObstacle->vecBBMin, 
			&currentObstacle->vecBBMax);

		// Unlock the vertex buffer
		m_pExtendedCollisionMesh->UnlockVertexBuffer();
		// with the min and max vectors we can get the 8 corners for the bounding box
		currentObstacle->vecModelBounds[0] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[1] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[2] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[3] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[4] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[5] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[6] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[7] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);

	}

	// Get attributes to draw bounding box
	float width, height, depth;
	width = currentObstacle->vecBBMax.x - currentObstacle->vecBBMin.x;
	height = currentObstacle->vecBBMax.y - currentObstacle->vecBBMin.y;
	depth = currentObstacle->vecBBMax.z - currentObstacle->vecBBMin.z;

	// Make a mesh
	D3DXCreateBox(m_Device, width, height, depth, &m_pBBAcidMesh, NULL);
	// Insert the current structure into the vector
	acidPitList.push_back(currentObstacle);

	return sAcidIndex++;
}

short ObstacleManager::CreatePiston(D3DXVECTOR3 vecPos)
{
	// Create the struct for this sepcific model
	s_Piston* currentObstacle = new s_Piston;

	// Start .x loading
	LPD3DXBUFFER p_D3DXMtrlBuffer;
	currentObstacle->m_dwNumMaterials = 0;

	// Load .x file
	D3DXLoadMeshFromX( "Models\\Piston.X", D3DXMESH_SYSTEMMEM,
		m_Device, NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials),
		&(currentObstacle->m_pMesh));

	D3DXMATERIAL* d3dxMaterials =
		(D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	// Create an array based on the amount of materials we have
	currentObstacle->m_pMaterials = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials];
	currentObstacle->m_pMeshTextures = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials];

	// Load each material
	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials; i++)
	{
		currentObstacle->m_pMaterials[i] = d3dxMaterials[i].MatD3D;

		currentObstacle->m_pMaterials[i].Ambient = currentObstacle->m_pMaterials[i].Diffuse;

		currentObstacle->m_pMeshTextures[i] = NULL;
		if( d3dxMaterials[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile( m_Device,
			d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures[i]));
		}
	}
	// End .x loading

	// Set the pos & scale for the model
	currentObstacle->vecScale = D3DXVECTOR3(0.5f, 0.5f, 0.5f);
	currentObstacle->vecPos = vecPos;
	currentObstacle->fYMin = 20.0f;
	currentObstacle->fYMax = 20.0f;	
	if(currentObstacle->vecPos.y > 2 && currentObstacle->vecPos.y < 5)
	{
		currentObstacle->bMaxHeight = false;
	}
	else
	{
		currentObstacle->bMaxHeight = true;
	}
	
	HRESULT hr = 0;
	BYTE* pVertices = 0;
	if( SUCCEEDED(currentObstacle->m_pMesh->LockVertexBuffer(0, (void**)&pVertices)))
	{
		// Locking the vertex buffer so we can compute the bounds
		hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, currentObstacle->m_pMesh->GetNumVertices(),
			D3DXGetFVFVertexSize(currentObstacle->m_pMesh->GetFVF()), &currentObstacle->vecBBMin, 
			&currentObstacle->vecBBMax);

		// Unlock the vertex buffer
		currentObstacle->m_pMesh->UnlockVertexBuffer();
		// with the min and max vectors we can get the 8 corners for the bounding box
		currentObstacle->vecModelBounds[0] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[1] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[2] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[3] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[4] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[5] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[6] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[7] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
	}

	// Insert the current structure into the vector
	pistonList.push_back(currentObstacle);

	return sPistonIndex++;
}

short ObstacleManager::CreateFirewall(D3DXVECTOR3 vecPos)
{
	// Create the struct for this sepcific model
	s_Firewall* currentObstacle = new s_Firewall;

	// Start .x loading
	LPD3DXBUFFER p_D3DXMtrlBuffer;
	currentObstacle->m_dwNumMaterials = 0;

	// Load .x file
	D3DXLoadMeshFromX( "Models\\Fire.X", D3DXMESH_SYSTEMMEM,
		m_Device, NULL, &p_D3DXMtrlBuffer, NULL, &(currentObstacle->m_dwNumMaterials),
		&(currentObstacle->m_pMesh));

	D3DXMATERIAL* d3dxMaterials =
		(D3DXMATERIAL*)p_D3DXMtrlBuffer->GetBufferPointer();

	// Create an array based on the amount of materials we have
	currentObstacle->m_pMaterials = new D3DMATERIAL9[currentObstacle->m_dwNumMaterials];
	currentObstacle->m_pMeshTextures = new LPDIRECT3DTEXTURE9[currentObstacle->m_dwNumMaterials];

	// Load each material
	for( DWORD i = 0; i < currentObstacle->m_dwNumMaterials; i++)
	{
		currentObstacle->m_pMaterials[i] = d3dxMaterials[i].MatD3D;

		currentObstacle->m_pMaterials[i].Ambient = currentObstacle->m_pMaterials[i].Diffuse;

		currentObstacle->m_pMeshTextures[i] = NULL;
		if( d3dxMaterials[i].pTextureFilename)
		{
			D3DXCreateTextureFromFile( m_Device,
			d3dxMaterials[i].pTextureFilename,
			&(currentObstacle->m_pMeshTextures[i]));
		}
	}
	// End .x loading

	// Set the pos & scale for the model
	currentObstacle->vecScale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
	currentObstacle->vecPos = vecPos;
	currentObstacle->vecRot = D3DXVECTOR3(-1.57f, 0.0f, 0.0f);

	HRESULT hr = 0;
	BYTE* pVertices = 0;
	if( SUCCEEDED(currentObstacle->m_pMesh->LockVertexBuffer(0, (void**)&pVertices)))
	{
		// Locking the vertex buffer so we can compute the bounds
		hr = D3DXComputeBoundingBox((D3DXVECTOR3*)pVertices, currentObstacle->m_pMesh->GetNumVertices(),
			D3DXGetFVFVertexSize(currentObstacle->m_pMesh->GetFVF()), &currentObstacle->vecBBMin, 
			&currentObstacle->vecBBMax);

		// Unlock the vertex buffer
		currentObstacle->m_pMesh->UnlockVertexBuffer();
		// with the min and max vectors we can get the 8 corners for the bounding box
		currentObstacle->vecModelBounds[0] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[1] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[2] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[3] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMin.z);
		currentObstacle->vecModelBounds[4] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[5] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMin.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[6] = D3DXVECTOR3(currentObstacle->vecBBMin.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
		currentObstacle->vecModelBounds[7] = D3DXVECTOR3(currentObstacle->vecBBMax.x, currentObstacle->vecBBMax.y, 
			currentObstacle->vecBBMax.z);
	}

	// Insert the current structure into the vector
	firewallList.push_back(currentObstacle);

	return sFirewallIndex++;
}

// Update obstacles
void ObstacleManager::Update(float deltaTime)
{
	// first call to update should start timer for the first time
	if(lStartTime == 0)
	{
		lStartTime = (LONG)timeGetTime();
	}
	lCurrentTime = (LONG)timeGetTime();

	lCurrentTime = lCurrentTime - lStartTime;

	if(lCurrentTime > 4000)
	{
		for(int i = 0; i< sTeslaIndex; i++)
		{
			if(teslaList[i]->bCharged)
				teslaList[i]->bCharged = false;
			else
				teslaList[i]->bCharged = true;
		}
		for(int i = 0; i < sAcidIndex; i++)
		{
			if(acidPitList[i]->bAcidSpray)
			{
				acidPitList[i]->bAcidSpray = false;
				acidPitList[i]->vecPos2 = acidPitList[i]->vecPos;
			}
			else
				acidPitList[i]->bAcidSpray = true;
		}
		// Reset Timer
		lStartTime = (LONG)timeGetTime();
	}
	
	// update to add a little movement to the static bubbles
	for(int i = 0; i < sAcidIndex; i++)
	{
		if(acidPitList[i]->bAcidSpray)
		{
			acidPitList[i]->vecPos2.y += (0.09f * deltaTime);
		}
	}
	for(int i = 0; i < sPistonIndex; i++)
	{
		if(pistonList[i]->bMaxHeight)
		{
			pistonList[i]->vecPos.y = pistonList[i]->vecPos.y - (4.0f * deltaTime);
			if(pistonList[i]->vecPos.y < 2)
				pistonList[i]->bMaxHeight = false;
		}
		else
		{
			pistonList[i]->vecPos.y = pistonList[i]->vecPos.y + (1.5f * deltaTime);
			if(pistonList[i]->vecPos.y > 5)
				pistonList[i]->bMaxHeight = true;
		}
	}
}
// Drawing models
void ObstacleManager::DrawModel(float deltaTime)
{
	for(int i = 0; i < sTeslaIndex; i++)
	{
		// Reset the matrices
		D3DXMatrixIdentity( &teslaList[i]->scaleMat);
		D3DXMatrixIdentity( &teslaList[i]->rotMat);
		D3DXMatrixIdentity( &teslaList[i]->transMat);
		D3DXMatrixIdentity( &teslaList[i]->worldMat);

		// Rotate, scale, and move the .x drawing
		D3DXMatrixScaling( &teslaList[i]->scaleMat, teslaList[i]->vecScale.x, teslaList[i]->vecScale.y, teslaList[i]->vecScale.z);
		//D3DXMatrixRotationYawPitchRoll( &teslaList[i]->rotMat, teslaList[i]->vecRot.x, teslaList[i]->vecRot.y, teslaList[i]->vecRot.z);
		D3DXMatrixTranslation( &teslaList[i]->transMat, teslaList[i]->vecPos.x, teslaList[i]->vecPos.y, teslaList[i]->vecPos.z);

		// Scale & rotation * translation
		D3DXMatrixMultiply( &teslaList[i]->scaleMat, &teslaList[i]->rotMat, &teslaList[i]->scaleMat);
		D3DXMatrixMultiply( &teslaList[i]->worldMat, &teslaList[i]->scaleMat, &teslaList[i]->transMat);

		m_Device->SetTransform( D3DTS_WORLD, &teslaList[i]->worldMat);

		// Start .x drawing
		for( DWORD j = 0; j < teslaList[i]->m_dwNumMaterials; j++)
		{
			m_Device->SetMaterial( &(teslaList[i]->m_pMaterials[j]));
			m_Device->SetTexture( 0, (teslaList[i]->m_pMeshTextures[j]));

			teslaList[i]->m_pMesh->DrawSubset(j);
		}

		m_Device->SetTexture(0, NULL);
		
		// if the tesla is charged then display electrified graphic on the tesla's
		if(teslaList[i]->bCharged)
		{
			D3DXMatrixIdentity( &teslaList[i]->scaleMat);
			D3DXMatrixScaling( &teslaList[i]->scaleMat, teslaList[i]->vecScale2.x, teslaList[i]->vecScale2.y,
					teslaList[i]->vecScale2.z);
			/*D3DXMatrixTranslation(&teslaList[i]->transMat, 0.0f, 0.2f, 0.0f);*/
			D3DXMatrixMultiply( &teslaList[i]->worldMat, &teslaList[i]->scaleMat, &teslaList[i]->transMat);
			m_Device->SetTransform( D3DTS_WORLD, &teslaList[i]->worldMat);
			for( DWORD j = 0; j < teslaList[i]->m_dwNumMaterials2; j++)
			{
				m_Device->SetMaterial(&(teslaList[i]->m_pMaterials2[j]));
				m_Device->SetTexture(0, (teslaList[i]->m_pMeshTextures2[j]));
				teslaList[i]->m_pMesh2->DrawSubset(j);
			}
			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			//		Testing code!!!!      Drawing Bounding Box to ensure it is correcly placed on model
			// Turning on Wireframe
			//m_Device->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

			// Draw box
			//m_pBBTeslaMesh->DrawSubset(0);

			// Turn off WireFrame
			//m_Device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		}
	}
	for(int i = 0; i < sAcidIndex; i++)
	{
		// Reset the matrices
		D3DXMatrixIdentity( &acidPitList[i]->scaleMat);
		D3DXMatrixIdentity( &acidPitList[i]->rotMat);
		D3DXMatrixIdentity( &acidPitList[i]->transMat);
		D3DXMatrixIdentity( &acidPitList[i]->worldMat);

		// Rotate, scale, and move the .x drawing
		D3DXMatrixScaling( &acidPitList[i]->scaleMat, acidPitList[i]->vecScale.x, acidPitList[i]->vecScale.y, acidPitList[i]->vecScale.z);
		D3DXMatrixRotationYawPitchRoll( &acidPitList[i]->rotMat, acidPitList[i]->vecRot.x, acidPitList[i]->vecRot.y, acidPitList[i]->vecRot.z);
		D3DXMatrixTranslation( &acidPitList[i]->transMat, acidPitList[i]->vecPos.x, acidPitList[i]->vecPos.y, acidPitList[i]->vecPos.z);

		D3DXMatrixMultiply( &acidPitList[i]->scaleMat, &acidPitList[i]->rotMat, &acidPitList[i]->scaleMat);
		D3DXMatrixMultiply( &acidPitList[i]->worldMat, &acidPitList[i]->scaleMat, &acidPitList[i]->transMat);

		m_Device->SetTransform( D3DTS_WORLD, &acidPitList[i]->worldMat);

		// Start .x drawing
		for( DWORD j = 0; j < acidPitList[i]->m_dwNumMaterials; j++)
		{
			m_Device->SetMaterial( &(acidPitList[i]->m_pMaterials[j]));
			m_Device->SetTexture( 0, (acidPitList[i]->m_pMeshTextures[j]));

			acidPitList[i]->m_pMesh->DrawSubset(j);
		}

		m_Device->SetTexture(0, NULL);
		// using wire frame box to show until acid spray animation can be implemented
		if(acidPitList[i]->bAcidSpray)
		{
			D3DXMatrixIdentity(&acidPitList[i]->rotMat);
			D3DXMatrixIdentity(&acidPitList[i]->scaleMat);
			D3DXMatrixIdentity(&acidPitList[i]->transMat);
			D3DXMatrixIdentity(&acidPitList[i]->worldMat2);
			D3DXMatrixScaling(&acidPitList[i]->scaleMat, acidPitList[i]->vecScale2.x,
				acidPitList[i]->vecScale2.y, acidPitList[i]->vecScale2.z);
			D3DXMatrixTranslation(&acidPitList[i]->transMat, acidPitList[i]->vecPos2.x, 
				acidPitList[i]->vecPos2.y, acidPitList[i]->vecPos2.z);
			D3DXMatrixMultiply(&acidPitList[i]->scaleMat, &acidPitList[i]->rotMat, &acidPitList[i]->scaleMat);
			D3DXMatrixMultiply(&acidPitList[i]->worldMat2, &acidPitList[i]->scaleMat, &acidPitList[i]->transMat);
			m_Device->SetTransform( D3DTS_WORLD, &acidPitList[i]->worldMat2);

			for( DWORD j = 0; j < acidPitList[i]->m_dwNumMaterials2; j++)
			{
				m_Device->SetMaterial( &(acidPitList[i]->m_pMaterials2[j]));
				m_Device->SetTexture(0, (acidPitList[i]->m_pMeshTextures2[j]));
				acidPitList[i]->m_pMesh2->DrawSubset(j);
			}
			m_Device->SetTexture(0, NULL);
			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			//		Testing code!!!!      Drawing Bounding Box to ensure it is correcly placed on model
			// Turning on Wireframe
			//m_Device->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );

			// Draw box
			//m_pBBAcidMesh->DrawSubset(0);

			// Turn off WireFrame
			//m_Device->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
			////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		}
	}
		for(int i = 0; i < sPistonIndex; i++)
	{
		// Reset the matrices
		D3DXMatrixIdentity( &pistonList[i]->scaleMat);
		D3DXMatrixIdentity( &pistonList[i]->rotMat);
		D3DXMatrixIdentity( &pistonList[i]->transMat);
		D3DXMatrixIdentity( &pistonList[i]->worldMat);

		// Rotate, scale, and move the .x drawing
		D3DXMatrixScaling( &pistonList[i]->scaleMat, pistonList[i]->vecScale.x, pistonList[i]->vecScale.y, pistonList[i]->vecScale.z);
		//D3DXMatrixRotationYawPitchRoll( &pistonList[i]->rotMat, pistonList[i]->vecRot.x, pistonList[i]->vecRot.y, pistonList[i]->vecRot.z);
		D3DXMatrixTranslation( &pistonList[i]->transMat, pistonList[i]->vecPos.x, pistonList[i]->vecPos.y, pistonList[i]->vecPos.z);

		// Scale & rotation * translation
		D3DXMatrixMultiply( &pistonList[i]->scaleMat, &pistonList[i]->rotMat, &pistonList[i]->scaleMat);
		D3DXMatrixMultiply( &pistonList[i]->worldMat, &pistonList[i]->scaleMat, &pistonList[i]->transMat);

		m_Device->SetTransform( D3DTS_WORLD, &pistonList[i]->worldMat);

		// Start .x drawing
		for( DWORD j = 0; j < pistonList[i]->m_dwNumMaterials; j++)
		{
			m_Device->SetMaterial( &(pistonList[i]->m_pMaterials[j]));
			m_Device->SetTexture( 0, (pistonList[i]->m_pMeshTextures[j]));

			pistonList[i]->m_pMesh->DrawSubset(j);
		}

		m_Device->SetTexture(0, NULL);		
	}
		for(int i = 0; i < sFirewallIndex; i++)
	{
		// Reset the matrices
		D3DXMatrixIdentity( &firewallList[i]->scaleMat);
		D3DXMatrixIdentity( &firewallList[i]->rotMat);
		D3DXMatrixIdentity( &firewallList[i]->transMat);
		D3DXMatrixIdentity( &firewallList[i]->worldMat);

		// Rotate, scale, and move the .x drawing
		D3DXMatrixScaling( &firewallList[i]->scaleMat, firewallList[i]->vecScale.x, firewallList[i]->vecScale.y, firewallList[i]->vecScale.z);
		D3DXMatrixRotationYawPitchRoll( &firewallList[i]->rotMat, firewallList[i]->vecRot.x, firewallList[i]->vecRot.y, firewallList[i]->vecRot.z);
		D3DXMatrixTranslation( &firewallList[i]->transMat, firewallList[i]->vecPos.x, firewallList[i]->vecPos.y, firewallList[i]->vecPos.z);

		// Scale & rotation * translation
		D3DXMatrixMultiply( &firewallList[i]->scaleMat, &firewallList[i]->rotMat, &firewallList[i]->scaleMat);
		D3DXMatrixMultiply( &firewallList[i]->worldMat, &firewallList[i]->scaleMat, &firewallList[i]->transMat);

		m_Device->SetTransform( D3DTS_WORLD, &firewallList[i]->worldMat);

		// Start .x drawing
		for( DWORD j = 0; j < firewallList[i]->m_dwNumMaterials; j++)
		{
			m_Device->SetMaterial( &(firewallList[i]->m_pMaterials[j]));
			m_Device->SetTexture( 0, (firewallList[i]->m_pMeshTextures[j]));

			firewallList[i]->m_pMesh->DrawSubset(j);
		}

		m_Device->SetTexture(0, NULL);		
	}
}

void ObstacleManager::CalculateTeslaBB(short sObstacleID)
{
	D3DXVECTOR3 worldBounds[8];
	for( int i = 0; i < 8; i++)
		D3DXVec3TransformCoord( &worldBounds[i], &teslaList[sObstacleID]->vecModelBounds[i], &teslaList[sObstacleID]->worldMat );

	// Pick a corner and set the smallest point and largest point to that corner
	teslaList[sObstacleID]->worldBBmin = worldBounds[0];
	teslaList[sObstacleID]->worldBBmax = worldBounds[0];

	// Find the new minimum and maximum points after transformation
	// Now, compare the other corners and see if they are smaller or larger
	for( short i = 1; i < 8; i++ )
	{
		if(worldBounds[i].x < teslaList[sObstacleID]->worldBBmin.x)
			teslaList[sObstacleID]->worldBBmin.x = worldBounds[i].x;
		if(worldBounds[i].x > teslaList[sObstacleID]->worldBBmax.x)
			teslaList[sObstacleID]->worldBBmax.x = worldBounds[i].x;
		if(worldBounds[i].y < teslaList[sObstacleID]->worldBBmin.y)
			teslaList[sObstacleID]->worldBBmin.y = worldBounds[i].y;
		if(worldBounds[i].y > teslaList[sObstacleID]->worldBBmax.y)
			teslaList[sObstacleID]->worldBBmax.y = worldBounds[i].y;
		if(worldBounds[i].z < teslaList[sObstacleID]->worldBBmin.z)
			teslaList[sObstacleID]->worldBBmin.z = worldBounds[i].z;
		if(worldBounds[i].z > teslaList[sObstacleID]->worldBBmax.z)
			teslaList[sObstacleID]->worldBBmax.z = worldBounds[i].z;	
	}
}

bool ObstacleManager::TeslaCollision(short sObstacleID)
{
	// Collision only matters if tesla coil is currently electrified
	if(teslaList[sObstacleID]->bCharged)
	{
		// Calculate the world space bounding box for player object
		modelMan->CalculateWorldBB(0);

		// Calculate the world space bounding box for other object
		CalculateTeslaBB(sObstacleID);

		// Collision check on the boundaries
		if(modelMan->modelList[0]->worldBBmax.x < teslaList[sObstacleID]->worldBBmin.x)
			return false;
		if(modelMan->modelList[0]->worldBBmax.y < teslaList[sObstacleID]->worldBBmin.y)
			return false;
		if(modelMan->modelList[0]->worldBBmax.z < teslaList[sObstacleID]->worldBBmin.z)
			return false;
		if(modelMan->modelList[0]->worldBBmin.x > teslaList[sObstacleID]->worldBBmax.x)
			return false;
		if(modelMan->modelList[0]->worldBBmin.y > teslaList[sObstacleID]->worldBBmax.y)
			return false;
		if(modelMan->modelList[0]->worldBBmin.z > teslaList[sObstacleID]->worldBBmax.z)
			return false;

		
		return true;
	}
	return false;
}

void ObstacleManager::CalculateAcidBB(short sObstacleID)
{
	D3DXVECTOR3 worldBounds[8];
	for( int i = 0; i < 8; i++)
		D3DXVec3TransformCoord( &worldBounds[i], &acidPitList[sObstacleID]->vecModelBounds[i], &acidPitList[sObstacleID]->worldMat );

	// Pick a corner and set the smallest point and largest point to that corner
	acidPitList[sObstacleID]->worldBBmin = worldBounds[0];
	acidPitList[sObstacleID]->worldBBmax = worldBounds[0];

	// Find the new minimum and maximum points after transformation
	// Now, compare the other corners and see if they are smaller or larger
	for( short i = 1; i < 8; i++ )
	{
		if(worldBounds[i].x < acidPitList[sObstacleID]->worldBBmin.x)
			acidPitList[sObstacleID]->worldBBmin.x = worldBounds[i].x;
		if(worldBounds[i].x > acidPitList[sObstacleID]->worldBBmax.x)
			acidPitList[sObstacleID]->worldBBmax.x = worldBounds[i].x;
		if(worldBounds[i].y < acidPitList[sObstacleID]->worldBBmin.y)
			acidPitList[sObstacleID]->worldBBmin.y = worldBounds[i].y;
		if(worldBounds[i].y > acidPitList[sObstacleID]->worldBBmax.y)
			acidPitList[sObstacleID]->worldBBmax.y = worldBounds[i].y;
		if(worldBounds[i].z < acidPitList[sObstacleID]->worldBBmin.z)
			acidPitList[sObstacleID]->worldBBmin.z = worldBounds[i].z;
		if(worldBounds[i].z > acidPitList[sObstacleID]->worldBBmax.z)
			acidPitList[sObstacleID]->worldBBmax.z = worldBounds[i].z;	
	}
}

bool ObstacleManager::AcidCollision(short sObstacleID)
{
	// Collision only matters if tesla coil is currently electrified
	if(acidPitList[sObstacleID]->bAcidSpray)
	{
		// Calculate the world space bounding box for player object
		modelMan->CalculateWorldBB(0);

		// Calculate the world space bounding box for other object
		CalculateAcidBB(sObstacleID);

		// Collision check on the boundaries
		if(modelMan->modelList[0]->worldBBmax.x < acidPitList[sObstacleID]->worldBBmin.x)
			return false;
		if(modelMan->modelList[0]->worldBBmax.y < acidPitList[sObstacleID]->worldBBmin.y)
			return false;
		if(modelMan->modelList[0]->worldBBmax.z < acidPitList[sObstacleID]->worldBBmin.z)
			return false;
		if(modelMan->modelList[0]->worldBBmin.x > acidPitList[sObstacleID]->worldBBmax.x)
			return false;
		if(modelMan->modelList[0]->worldBBmin.y > acidPitList[sObstacleID]->worldBBmax.y)
			return false;
		if(modelMan->modelList[0]->worldBBmin.z > acidPitList[sObstacleID]->worldBBmax.z)
			return false;
		
		return true;
	}
	return false;
}

void ObstacleManager::CalculatePistonBB(short sObstacleID)
{
	D3DXVECTOR3 worldBounds[8];
	for( int i = 0; i < 8; i++)
		D3DXVec3TransformCoord( &worldBounds[i], &pistonList[sObstacleID]->vecModelBounds[i], &pistonList[sObstacleID]->worldMat );

	// Pick a corner and set the smallest point and largest point to that corner
	pistonList[sObstacleID]->worldBBmin = worldBounds[0];
	pistonList[sObstacleID]->worldBBmax = worldBounds[0];

	// Find the new minimum and maximum points after transformation
	// Now, compare the other corners and see if they are smaller or larger
	for( short i = 1; i < 8; i++ )
	{
		if(worldBounds[i].x < pistonList[sObstacleID]->worldBBmin.x)
			pistonList[sObstacleID]->worldBBmin.x = worldBounds[i].x;
		if(worldBounds[i].x > pistonList[sObstacleID]->worldBBmax.x)
			pistonList[sObstacleID]->worldBBmax.x = worldBounds[i].x;
		if(worldBounds[i].y < pistonList[sObstacleID]->worldBBmin.y)
			pistonList[sObstacleID]->worldBBmin.y = worldBounds[i].y;
		if(worldBounds[i].y > pistonList[sObstacleID]->worldBBmax.y)
			pistonList[sObstacleID]->worldBBmax.y = worldBounds[i].y;
		if(worldBounds[i].z < pistonList[sObstacleID]->worldBBmin.z)
			pistonList[sObstacleID]->worldBBmin.z = worldBounds[i].z;
		if(worldBounds[i].z > pistonList[sObstacleID]->worldBBmax.z)
			pistonList[sObstacleID]->worldBBmax.z = worldBounds[i].z;	
	}
}

bool ObstacleManager::PistonCollision(short sObstacleID)
{
	// Calculate the world space bounding box for player object
	modelMan->CalculateWorldBB(0);

	// Calculate the world space bounding box for other object
	CalculatePistonBB(sObstacleID);

	// Collision check on the boundaries
	if(modelMan->modelList[0]->worldBBmax.x < pistonList[sObstacleID]->worldBBmin.x)
		return false;
	if(modelMan->modelList[0]->worldBBmax.y < pistonList[sObstacleID]->worldBBmin.y)
		return false;
	if(modelMan->modelList[0]->worldBBmax.z < pistonList[sObstacleID]->worldBBmin.z)
		return false;
	if(modelMan->modelList[0]->worldBBmin.x > pistonList[sObstacleID]->worldBBmax.x)
		return false;
	if(modelMan->modelList[0]->worldBBmin.y > pistonList[sObstacleID]->worldBBmax.y)
		return false;
	if(modelMan->modelList[0]->worldBBmin.z > pistonList[sObstacleID]->worldBBmax.z)
		return false;
	
	return true;
}

void ObstacleManager::CalculateFirewallBB(short sObstacleID)
{
	D3DXVECTOR3 worldBounds[8];
	for( int i = 0; i < 8; i++)
		D3DXVec3TransformCoord( &worldBounds[i], &firewallList[sObstacleID]->vecModelBounds[i], &firewallList[sObstacleID]->worldMat );

	// Pick a corner and set the smallest point and largest point to that corner
	firewallList[sObstacleID]->worldBBmin = worldBounds[0];
	firewallList[sObstacleID]->worldBBmax = worldBounds[0];

	// Find the new minimum and maximum points after transformation
	// Now, compare the other corners and see if they are smaller or larger
	for( short i = 1; i < 8; i++ )
	{
		if(worldBounds[i].x < firewallList[sObstacleID]->worldBBmin.x)
			firewallList[sObstacleID]->worldBBmin.x = worldBounds[i].x;
		if(worldBounds[i].x > firewallList[sObstacleID]->worldBBmax.x)
			firewallList[sObstacleID]->worldBBmax.x = worldBounds[i].x;
		if(worldBounds[i].y < firewallList[sObstacleID]->worldBBmin.y)
			firewallList[sObstacleID]->worldBBmin.y = worldBounds[i].y;
		if(worldBounds[i].y > firewallList[sObstacleID]->worldBBmax.y)
			firewallList[sObstacleID]->worldBBmax.y = worldBounds[i].y;
		if(worldBounds[i].z < firewallList[sObstacleID]->worldBBmin.z)
			firewallList[sObstacleID]->worldBBmin.z = worldBounds[i].z;
		if(worldBounds[i].z > firewallList[sObstacleID]->worldBBmax.z)
			firewallList[sObstacleID]->worldBBmax.z = worldBounds[i].z;	
	}
}

bool ObstacleManager::FirewallCollision(short iObstacle)
{	
	// Calculate the world space bounding box for player object
	modelMan->CalculateWorldBB(0);

	// Calculate the world space bounding box for other object
	CalculateFirewallBB(iObstacle);

	// Collision check on the boundaries
	if(modelMan->modelList[0]->worldBBmax.x < firewallList[iObstacle]->worldBBmin.x)
		return false;
	if(modelMan->modelList[0]->worldBBmax.y < firewallList[iObstacle]->worldBBmin.y)
		return false;
	if(modelMan->modelList[0]->worldBBmax.z < firewallList[iObstacle]->worldBBmin.z)
		return false;		
	if(modelMan->modelList[0]->worldBBmin.x > firewallList[iObstacle]->worldBBmax.x)
		return false;			
	if(modelMan->modelList[0]->worldBBmin.y > firewallList[iObstacle]->worldBBmax.y)
		return false;				
	if(modelMan->modelList[0]->worldBBmin.z > firewallList[iObstacle]->worldBBmax.z)
		return false;		

	// Collision occured
	return true;	
}

// Function to specifically run through the firewall collisions, so we can return immediately
// only if we have a collision.
bool ObstacleManager::FireWallLoop(void)
{
	for(int i = 0; i < sFirewallIndex; i++)
	{
		if(FirewallCollision(i))
			return true; // return immediately on collision
	}
	return false;
}

void ObstacleManager::DestroyAllObstacles(void)
{
	/////////////////////////////////////////////////////////////////////////////
	// .x file deleting	
	for(int i = sTeslaIndex - 1; i >= 0; i--)
	{
		if(teslaList[i]->m_pMaterials != NULL)
		{
			delete teslaList[i]->m_pMaterials;
			teslaList[i]->m_pMaterials = NULL;
		}
		if(teslaList[i]->m_pMaterials2 != NULL)
		{
			delete teslaList[i]->m_pMaterials2;
			teslaList[i]->m_pMaterials2 = NULL;
		}

		if(teslaList[i]->m_pMeshTextures)
		{
			for(DWORD j = 0; j < teslaList[i]->m_dwNumMaterials; j++)
			{
				if(teslaList[i]->m_pMeshTextures[j])
				{
					teslaList[i]->m_pMeshTextures[j]->Release();
					teslaList[i]->m_pMeshTextures[j] = NULL;
				}
			}

			delete[] teslaList[i]->m_pMeshTextures;
			teslaList[i]->m_pMeshTextures = NULL;
		}
		if(teslaList[i]->m_pMeshTextures2)
		{
			for(DWORD j = 0; j < teslaList[i]->m_dwNumMaterials2; j++)
			{
				if(teslaList[i]->m_pMeshTextures2[j])
				{
					teslaList[i]->m_pMeshTextures2[j]->Release();
					teslaList[i]->m_pMeshTextures2[j] = NULL;
				}
			}
			delete[] teslaList[i]->m_pMeshTextures2;
			teslaList[i]->m_pMeshTextures = NULL;
		}
		if(teslaList[i]->m_pMesh)
		{
			teslaList[i]->m_pMesh->Release();
			teslaList[i]->m_pMesh = NULL;
		}
		if(teslaList[i]->m_pMesh2)
		{
			teslaList[i]->m_pMesh2->Release();
			teslaList[i]->m_pMesh2 = NULL;
		}
		delete teslaList[i];
		teslaList[i] = NULL;
		teslaList.pop_back();
	}
	sTeslaIndex = 0;
	for(int i = sAcidIndex - 1; i >= 0; i--)
	{
		if(acidPitList[i]->m_pMaterials != NULL)
		{
			delete acidPitList[i]->m_pMaterials;
			acidPitList[i]->m_pMaterials = NULL;
		}
		if(acidPitList[i]->m_pMaterials2 != NULL)
		{
			delete acidPitList[i]->m_pMaterials2;
			acidPitList[i]->m_pMaterials2 = NULL;
		}
		if(acidPitList[i]->m_pMeshTextures)
		{
			for(DWORD j = 0; j < acidPitList[i]->m_dwNumMaterials; j++)
			{
				if(acidPitList[i]->m_pMeshTextures[j])
				{
					acidPitList[i]->m_pMeshTextures[j]->Release();
					acidPitList[i]->m_pMeshTextures[j] = NULL;
				}
			}
			delete[] acidPitList[i]->m_pMeshTextures;
			acidPitList[i]->m_pMeshTextures = NULL;
		}
		if(acidPitList[i]->m_pMeshTextures2)
		{
			for(DWORD j = 0; j < acidPitList[i]->m_dwNumMaterials2; j++)
			{
				if(acidPitList[i]->m_pMeshTextures2[j])
				{
					acidPitList[i]->m_pMeshTextures2[j]->Release();
					acidPitList[i]->m_pMeshTextures2[j] = NULL;
				}
			}
			delete[] acidPitList[i]->m_pMeshTextures2;
			acidPitList[i]->m_pMeshTextures2 = NULL;
		}
		if(acidPitList[i]->m_pMesh)
		{
			acidPitList[i]->m_pMesh->Release();
			acidPitList[i]->m_pMesh = NULL;
		}
		if(acidPitList[i]->m_pMesh2)
		{
			acidPitList[i]->m_pMesh2->Release();
			acidPitList[i]->m_pMesh2 = NULL;
		}
		delete acidPitList[i];
		acidPitList[i] = NULL;
		acidPitList.pop_back();
	}
	sAcidIndex = 0;
	for(int i = sPistonIndex - 1; i >= 0; i--)
	{
		if(pistonList[i]->m_pMaterials != NULL)
		{
			delete pistonList[i]->m_pMaterials;
			pistonList[i]->m_pMaterials = NULL;
		}

		if(pistonList[i]->m_pMeshTextures)
		{
			for(DWORD j = 0; j < pistonList[i]->m_dwNumMaterials; j++)
			{
				if(pistonList[i]->m_pMeshTextures[j])
				{
					pistonList[i]->m_pMeshTextures[j]->Release();
					pistonList[i]->m_pMeshTextures[j] = NULL;
				}
			}

			delete[] pistonList[i]->m_pMeshTextures;
			pistonList[i]->m_pMeshTextures = NULL;
		}

		if(pistonList[i]->m_pMesh)
		{
			pistonList[i]->m_pMesh->Release();
			pistonList[i]->m_pMesh = NULL;
		}
		delete pistonList[i];
		pistonList[i] = NULL;
		pistonList.pop_back();
	}
	sPistonIndex = 0;
	for(int i = sFirewallIndex - 1; i >= 0; i--)
	{
		if(firewallList[i]->m_pMaterials != NULL)
		{
			delete firewallList[i]->m_pMaterials;
			firewallList[i]->m_pMaterials = NULL;
		}

		if(firewallList[i]->m_pMeshTextures)
		{
			for(DWORD j = 0; j < firewallList[i]->m_dwNumMaterials; j++)
			{
				if(firewallList[i]->m_pMeshTextures[j])
				{
					firewallList[i]->m_pMeshTextures[j]->Release();
					firewallList[i]->m_pMeshTextures[j] = NULL;
				}
			}

			delete[] firewallList[i]->m_pMeshTextures;
			firewallList[i]->m_pMeshTextures = NULL;
		}

		if(firewallList[i]->m_pMesh)
		{
			firewallList[i]->m_pMesh->Release();
			firewallList[i]->m_pMesh = NULL;
		}
		delete firewallList[i];
		firewallList[i] = NULL;
		firewallList.pop_back();
	}
	sFirewallIndex = 0;
}
